﻿/********************************************************************
	created:	2011-8-10   15:01
	author:		Lifan Su
	
	purpose:	test code, C++ version
*********************************************************************/


#ifdef __cplusplus

#include "nullptr.hpp"
#include "_cinttyps.hpp"
#include "configure.h"

#include <cstdio>
#include <iostream>
#include <csignal>
#include <cstddef>
#include <cstdlib>
#include <cmath>

using std::printf;
using std::cout;
using std::endl;


using std::uint8_t;
using std::uint16_t;
using std::uint32_t;
using std::uint64_t;
using std::uintmax_t;
using std::uintptr_t;

using std::int8_t;
using std::int16_t;
using std::int32_t;
using std::int64_t;
using std::intmax_t;
using std::intptr_t;

using std::size_t;
using std::wint_t;

using std::nullptr_t;


void test_size(void);
void test_print(void);
void test_limit(void);
void test_limit_iostream(void);
void test_macro(void);
void test_nullptr(void);
void test_int(int x);
void test_ptr(void *p);
void test_overload(int i);
void test_overload(void *p);
void test_imax(void);


int main()
{
    test_size();
    test_print();
    test_limit();
    test_limit_iostream();
    test_macro();
    test_nullptr();
    test_imax();
    
    printf("\npress any key to continue...");
    getchar();
}


void test_size(void)
{
    printf("size of int8_t is %d\n",       sizeof(int8_t));
    printf("size of int16_t is %d\n",      sizeof(int16_t));
    printf("size of int32_t is %d\n",      sizeof(int32_t));
    printf("size of int64_t is %d\n",      sizeof(int64_t));
    printf("size of intmax_t is %d\n",     sizeof(intmax_t));
    printf("size of intptr_t is %d\n",     sizeof(intptr_t));

    printf("size of uint8_t is %d\n",      sizeof(uint8_t));
    printf("size of uint16_t is %d\n",     sizeof(uint16_t));
    printf("size of uint32_t is %d\n",     sizeof(uint32_t));
    printf("size of uint64_t is %d\n",     sizeof(uint64_t));
    printf("size of uintmax_t is %d\n",    sizeof(uintmax_t));
    printf("size of uintptr_t is %d\n",    sizeof(uintptr_t));
}

void test_print(void)
{
    int8_t      i8      = INT8_C(-1);
    int16_t     i16     = INT16_C(-2);
    int32_t     i32     = INT32_C(-3);
    int64_t     i64     = INT64_C(-4);
    intmax_t    imax    = INTMAX_C(-5);
    uint8_t     u8      = UINT8_C(0xab);
    uint16_t    u16     = UINT16_C(0xabcd);
    uint32_t    u32     = UINT32_C(0x89abcdef);
    uint64_t    u64     = UINT64_C(0xfedcba9876543210);
    uintmax_t   umax    = UINTMAX_C(0xfedcba9876543210);

    printf("\'PRId\'series \n");
    printf("int8_t: %"      PRId8 "\n",     i8);
    printf("int16_t: %"     PRId16 "\n",    i16);
    printf("int32_t: %"     PRId32 "\n",    i32);
    printf("int64_t: %"     PRId64 "\n",    i64);
    printf("intmax_t: %"    PRIdMAX "\n",   imax);

    printf("\'PRIi\'series \n");
    printf("int8_t: %"      PRIi8 "\n",     i8);
    printf("int16_t: %"     PRIi16 "\n",    i16);
    printf("int32_t: %"     PRIi32 "\n",    i32);
    printf("int64_t: %"     PRIi64 "\n",    i64);
    printf("intmax_t: %"    PRIiMAX "\n",   imax);


    printf("\'PRIo\'series \n");
    printf("uint8_t: %"     PRIo8 "\n",     u8);
    printf("uint16_t: %"    PRIo16 "\n",    u16);
    printf("uint32_t: %"    PRIo32 "\n",    u32);
    printf("uint64_t: %"    PRIo64 "\n",    u64);
    printf("uintmax_t: %"   PRIoMAX "\n",   umax);

    printf("\'PRIu\'series \n");
    printf("uint8_t: %"     PRIu8 "\n",     u8);
    printf("uint16_t: %"    PRIu16 "\n",    u16);
    printf("uint32_t: %"    PRIu32 "\n",    u32);
    printf("uint64_t: %"    PRIu64 "\n",    u64);
    printf("uintmax_t: %"   PRIuMAX "\n",   umax);

    printf("\'PRIx\'series \n");
    printf("uint8_t: %"     PRIx8 "\n",     u8);
    printf("uint16_t: %"    PRIx16 "\n",    u16);
    printf("uint32_t: %"    PRIx32 "\n",    u32);
    printf("uint64_t: %"    PRIx64 "\n",    u64);
    printf("uintmax_t: %"   PRIxMAX "\n",   umax);

    printf("\'PRIX\'series \n");
    printf("uint8_t: %"     PRIX8 "\n",     u8);
    printf("uint16_t: %"    PRIX16 "\n",    u16);
    printf("uint32_t: %"    PRIX32 "\n",    u32);
    printf("uint64_t: %"    PRIX64 "\n",    u64);
    printf("uintmax_t: %"   PRIXMAX "\n",   umax);


    int a[2] = {0, 1};
    printf("intptr_t\n");
    printf("intptr_t: %"    PRIdPTR "\n",   reinterpret_cast<intptr_t>(a + 0));
    printf("intptr_t: %"    PRIdPTR "\n",   reinterpret_cast<intptr_t>(a + 1));

    printf("uintptr_t\n");
    printf("uintptr_t: %"   PRIxPTR "\n",   reinterpret_cast<uintptr_t>(a + 0));
    printf("uintptr_t: %"   PRIxPTR "\n",   reinterpret_cast<uintptr_t>(a + 1));
}

void test_limit(void)
{
    printf("int8_t   min:%" PRId8 ", int8_t   max:%" PRId8 ", uint8_t   max:%" PRIu8 "\n", INT8_MIN,   INT8_MAX,   UINT8_MAX);
    printf("int16_t  min:%" PRId16 ", int16_t  max:%" PRId16 ", uint16_t  max:%" PRIu16 "\n", INT16_MIN,  INT16_MAX,  UINT16_MAX);
    printf("int32_t  min:%" PRId32 ", int32_t  max:%" PRId32 ", uint32_t  max:%" PRIu32 "\n", INT32_MIN,  INT32_MAX,  UINT32_MAX);
    printf("int64_t  min:%" PRId64 ", int64_t  max:%" PRId64 ", uint64_t  max:%" PRIu64 "\n", INT64_MIN,  INT64_MAX,  UINT64_MAX);
    printf("intmax_t min:%" PRIdMAX ", intmax_t max:%" PRIdMAX ", uintmax_t max:%" PRIuMAX "\n", INTMAX_MIN, INTMAX_MAX, UINTMAX_MAX);
    printf("intptr_t min:%" PRIdPTR ", intptr_t max:%" PRIdPTR ", uintptr_t max:%" PRIuPTR "\n", INTPTR_MIN, INTPTR_MAX, UINTPTR_MAX);
    printf("intato_t min:%" PRIdPTR ", intato_t max:%" PRIdPTR ", uintato_t max:--\n", sig_atomic_t(SIG_ATOMIC_MIN), sig_atomic_t(SIG_ATOMIC_MAX));
    printf("wchar_t  min:%" PRIu16 ", wchar_t  max:%" PRIu16 ", uwchar_t  max:--\n", wchar_t(WCHAR_MIN),  wchar_t(WCHAR_MAX));
    printf("wint_t   min:%" PRIu16 ", wint_t   max:%" PRIu16 ", uwint_t   max:--\n", wint_t(WINT_MIN),  wint_t(WINT_MAX));
    printf("size_t   min:--, size_t   max:%" PRIuMAX ", usize_t max:--\n", intmax_t(SIZE_MAX));
}

void test_limit_iostream(void)
{
    cout << "int8_t  min:" << INT8_MIN  << "\tint8_t  max:" << INT8_MAX  << "\tuint8_t  max:" << UINT8_MAX  << endl;
    cout << "int16_t min:" << INT16_MIN << "\tint16_t max:" << INT16_MAX << "\tuint16_t max:" << UINT16_MAX << endl;
    cout << "int32_t min:" << INT32_MIN << "\tint32_t max:" << INT32_MAX << "\tuint32_t max:" << UINT32_MAX << endl;
    cout << "int64_t min:" << INT64_MIN << "\tint64_t max:" << INT64_MAX << "\tuint64_t max:" << UINT64_MAX << endl;
    cout << "intmax_t min:" << INTMAX_MIN << "\tintmax_t max:" << INTMAX_MAX << "\tuintmax_t max:" << UINTMAX_MAX << endl;
    cout << "intptr_t min:" << INTPTR_MIN << "\tintptr_t max:" << INTPTR_MAX << "\tuintptr_t max:" << UINTPTR_MAX << endl;
    cout << "intato_t min:" << SIG_ATOMIC_MIN << "\tintato_t max:" << SIG_ATOMIC_MAX << endl;
    cout << "wchar_t min:" << WCHAR_MIN << "\twchar_t max:" << WCHAR_MAX << endl;
    cout << "wint_t  min:" << WINT_MIN  << "\twint_t  max:" << WINT_MAX  << endl;
    cout << "size_t  max:" << SIZE_MAX << endl;
}

void test_macro(void)
{
#ifdef _MSC_VER
    printf("_MSC_VER defined\n");
#endif // _MSC_VER

#ifdef _M_IX86
    printf("_M_IX86 defined\n");
#endif // _M_IX86

#ifdef _M_X64
    printf("_M_X64 defined\n");
#endif // _M_X64

#ifdef _M_AMD64
    printf("_M_AMD64 defined\n");
#endif // _M_AMD64

#ifdef __LITTLE_ENDIAN__
    printf("__LITTLE_ENDIAN__ defined\n");
#endif // __LITTLE_ENDIAN__

#ifdef __BIG_ENDIAN__
    printf("__BIG_ENDIAN__ defined\n");
#endif // __BIG_ENDIAN__
}



void test_nullptr(void)
{
    int a = 1;
    int *p = &a;

    printf("testing test_int\n");
    printf("test int (0): \t");
    test_int(0);
    printf("test int (a): \t");
    test_int(a);

    printf("testing test_ptr\n");
    printf("test void * (nullptr): \t");
    test_ptr(nullptr);
    printf("test void * (0): \t");
    test_ptr(0);
    printf("test void * (&a): \t");
    test_ptr(p);

    printf("testing test_overload\n");
    printf("test void * (nullptr): \t");
    test_overload(nullptr);
    printf("test void * (p): \t");
    test_overload(p);
    printf("test integer (0): \t");
    test_overload(0);
    printf("test integer (a): \t");
    test_overload(a);
}

void test_int(int x)
{
    printf("this is a overload of int.\t");
    if (x == 0) {
        printf("x is zero");
    }
    printf("\n");
}

void test_ptr(void *p)
{
    printf("this is a overload of void *.\t");
    if (!p/* == 0*/) {
        printf("p is empty pointer");
    }
    printf("\n");
}

void test_overload(int i)
{
    printf("this is a overload of int.\n");
}

void test_overload(void *p)
{
    printf("this is a overload of void *.\t");
    if (!p/* == 0*/) {
        printf("p is empty pointer");
    }
    printf("\n");
}

void test_imax(void)
{
    std::imaxdiv_t a = std::imaxdiv(INTMAX_C(0x7ffffffe7fff7fff), INTMAX_C(0x7fff7fff));
    printf("quot is %" PRIdMAX "\t; rem is %" PRIdMAX "\n", a.quot, a.rem);
    cout << "quot is " << a.quot << "\t rem is " << a.rem << endl;

    a = std::imaxdiv(INTMAX_C(0x7fff7fffffff7fff), INTMAX_C(0x7fff7ffff));
    printf("quot is %" PRIdMAX "\t; rem is %" PRIdMAX "\n", a.quot, a.rem);
    cout << "quot is " << a.quot << "\t rem is " << a.rem << endl;

    cout << std::strtoimax("-3421443214432555212", NULL, 10) << endl;
    cout << std::strtoumax("ffffffffffffffff", NULL, 16) << endl;
    cout << std::wcstoimax(L"-3235211333222111333", NULL, 10) << endl;
    cout << std::wcstoumax(L"ffffffffffffffff", NULL, 16) << endl;

    printf("%" PRIdMAX "\n", std::strtoimax("-3421443214432555212", NULL, 10));
    printf("%" PRIuMAX "\n", std::strtoumax("ffffffffffffffff", NULL, 16));
    printf("%" PRIdMAX "\n", std::wcstoimax(L"-3235211333222111333", NULL, 10));
    printf("%" PRIuMAX "\n", std::wcstoumax(L"ffffffffffffffff", NULL, 16));
}

#endif